package com.loong.android;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.ArrayList;

/**
 * 权限工具
 */
public class PermissionUtils {

    private static Activity getActivity() {
        LonApp app = LonApp.getInstance();
        if (app == null) return null;
        return app.getCurrentActivity();
    }

    private static LonWin getWin() {
        LonApp app = LonApp.getInstance();
        if (app == null) return null;
        Activity activity = app.getCurrentActivity();
        if (!(activity instanceof LonWin)) return null;
        return (LonWin) activity;
    }

    /**
     * 在指定窗口上申请权限
     *
     * @param win          窗口对象
     * @param permissions 权限数组
     * @param callback    回调
     */
    public static void applyPermission(LonWin win, String[] permissions, Callback callback) {
        if (win == null || permissions == null || permissions.length <= 0) return;
        //低于6.0不需要动态申请权限，直接全部返回已授权
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || checkPermission(win, permissions).length <= 0) {
            if (callback != null) callback.onResult(true, permissions, null);
            return;
        }
        if (callback != null) {
            final String listenerName = "RequestPermission" + System.currentTimeMillis();
            win.addWinLifeListener("RequestPermission", new WinLife() {
                @Override
                public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
                    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
                    if(requestCode != 0) return;
                    win.removeWinLifeListener(listenerName);
                    boolean res = false;
                    ArrayList<String> granted = new ArrayList<>();
                    ArrayList<String> denied = new ArrayList<>();
                    if (permissions.length > 0) {
                        res = true;
                        for (int i = 0; i < permissions.length; i++) {
                            if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
                                res = false;
                                denied.add(permissions[i]);
                            } else {
                                granted.add(permissions[i]);
                            }
                        }
                    }
                    callback.onResult(
                            res,
                            granted.toArray(new String[granted.size()]),
                            denied.toArray(new String[denied.size()])
                    );
                }
            });
        }
        win.requestPermissions(permissions, 0);
    }

    /**
     * 从当前的窗口申请权限
     *
     * @param permissions 权限数组
     * @param callback    回调
     */
    public static void applyPermission(String[] permissions, Callback callback) {
        LonWin win = getWin();
        if (win == null) return;
        applyPermission(win, permissions, callback);
    }

    /**
     * 检查权限是否已获得授权
     *
     * @param win        窗口
     * @param permission 权限
     */
    public static boolean checkPermission(LonWin win, String permission) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true;
        if (win == null || TextUtils.isEmpty(permission)) return false;
        return win.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * 检查权限是否已获得授权
     *
     * @param permission 权限
     */
    public static boolean checkPermission(String permission) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true;
        if (TextUtils.isEmpty(permission)) return false;
        Activity activity = getActivity();
        if (activity == null) return false;
        return activity.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * 检查多个权限是否已获得授权，返回未授权的权限数组
     *
     * @param win         窗口
     * @param permissions 权限数组
     */
    public static String[] checkPermission(LonWin win, String[] permissions) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return new String[0];
        if (win == null || permissions == null || permissions.length <= 0) return new String[0];
        ArrayList<String> denied = new ArrayList<>();
        for (int i = 0; i < permissions.length; i++) {
            if (win.checkSelfPermission(permissions[i]) == PackageManager.PERMISSION_DENIED) {
                denied.add(permissions[i]);
            }
        }
        return denied.toArray(new String[denied.size()]);
    }

    /**
     * 检查多个权限是否已获得授权，返回未授权的权限数组
     *
     * @param permissions 权限数组
     */
    public static String[] checkPermission(String[] permissions) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return new String[0];
        if (permissions == null || permissions.length <= 0) return new String[0];

        Activity activity = getActivity();
        if (activity == null) return new String[0];

        ArrayList<String> denied = new ArrayList<>();
        for (int i = 0; i < permissions.length; i++) {
            if (activity.checkSelfPermission(permissions[i]) == PackageManager.PERMISSION_DENIED) {
                denied.add(permissions[i]);
            }
        }
        return denied.toArray(new String[denied.size()]);
    }

    /**
     * 判断指定权限是否需要给用户展示申请权限原因，
     * 以提醒用户权限的重要性，防止用户拒绝权限并设置不再提醒
     * 当用户之前拒绝过权限申请请求，返回true
     *
     * @param win        窗口
     * @param permission 权限
     */
    public static boolean shouldShowRequestPermissionRationale(LonWin win, String permission) {
        if (Build.VERSION.SDK_INT < 23) return false;
        if (win == null || TextUtils.isEmpty(permission)) return false;
        return win.shouldShowRequestPermissionRationale(permission);
    }

    /**
     * 判断指定权限是否需要给用户展示申请权限原因，
     * 以提醒用户权限的重要性，防止用户拒绝权限并设置不再提醒
     * 当用户之前拒绝过权限申请请求，返回true
     *
     * @param permission 权限
     */
    public static boolean shouldShowRequestPermissionRationale(String permission) {
        if (Build.VERSION.SDK_INT < 23) return false;
        if (TextUtils.isEmpty(permission)) return false;
        Activity activity = getActivity();
        if (activity == null) return false;
        return activity.shouldShowRequestPermissionRationale(permission);
    }

    /**
     * 判断多个权限是否需要给用户展示申请权限原因，
     * 以提醒用户权限的重要性，防止用户拒绝权限并设置不再提醒。
     * 当用户之前拒绝过权限申请请求，返回需要显示的权限数组
     *
     * @param win         窗口
     * @param permissions 权限数组
     */
    public static String[] shouldShowRequestPermissionRationale(LonWin win, String[] permissions) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return new String[0];
        if (win == null || permissions == null || permissions.length <= 0) return new String[0];
        ArrayList<String> should = new ArrayList<>();
        for (int i = 0; i < permissions.length; i++) {
            if (win.shouldShowRequestPermissionRationale(permissions[i])) {
                should.add(permissions[i]);
            }
        }
        return should.toArray(new String[should.size()]);
    }

    /**
     * 判断多个权限是否需要给用户展示申请权限原因，
     * 以提醒用户权限的重要性，防止用户拒绝权限并设置不再提醒。
     * 当用户之前拒绝过权限申请请求，返回需要显示的权限数组
     *
     * @param permissions 权限数组
     */
    public static String[] shouldShowRequestPermissionRationale(String[] permissions) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return new String[0];
        if (permissions == null || permissions.length <= 0) return new String[0];

        Activity activity = getActivity();
        if (activity == null) return new String[0];

        ArrayList<String> should = new ArrayList<>();
        for (int i = 0; i < permissions.length; i++) {
            if (activity.shouldShowRequestPermissionRationale(permissions[i])) {
                should.add(permissions[i]);
            }
        }
        return should.toArray(new String[should.size()]);
    }

    /**
     * 申请安装未知来源APP权限。注意，需要添加权限："REQUEST_INSTALL_PACKAGES"
     */
    public static void requestUnknownSourceAppPermission(LonWin win, RequestUnknownSourceAppCallback callback){
        if(Build.VERSION.SDK_INT >= 26 && !win.getPackageManager().canRequestPackageInstalls()) {
            //API26 即 Android8.0以上需要弹出一个"允许安装未知来源"的设置界面。
            Uri packageURI = Uri.parse("package:" + win.getPackageName());
            Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI);
            win.startActivityForResult(intent, 2022);
            String lifeName = "requestUnknownSourceApp" + System.currentTimeMillis();
            win.addWinLifeListener(lifeName, new WinLife() {
                @Override
                public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
                    super.onActivityResult(requestCode, resultCode, data);
                    if(requestCode != 2022) return;
                    win.removeWinLifeListener(lifeName);
                    if (callback != null) {
                        callback.onResult(win.getPackageManager().canRequestPackageInstalls());
                    }
                }
            });
            return;
        }
        if(callback != null) callback.onResult(true);
    }

    /**
     * 申请安装位置来源应用的接口事件
     */
    public abstract static class RequestUnknownSourceAppCallback {
        /**
         * 权限申请完毕的回调
         * @param res 结果
         */
        public void onResult(boolean res) {

        }
    }

    public abstract static class Callback {
        public void onResult(boolean result, String[] granted, String[] denied) { }
    }

    /**
     * 需要动态申请的危险权限
     */
    public static class Permission {
        public static final String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
        public static final String ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION";
        public static final String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL";
        public static final String ANSWER_PHONE_CALLS = "android.permission.ANSWER_PHONE_CALLS";
        public static final String BODY_SENSORS = "android.permission.BODY_SENSORS";
        public static final String CALL_PHONE = "android.permission.CALL_PHONE";
        public static final String CAMERA = "android.permission.CAMERA";
        public static final String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
        public static final String READ_CALENDAR = "android.permission.READ_CALENDAR";
        public static final String READ_CALL_LOG = "android.permission.READ_CALL_LOG";
        public static final String READ_CONTACTS = "android.permission.READ_CONTACTS";
        public static final String READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE";
        public static final String READ_PHONE_NUMBERS = "android.permission.READ_PHONE_NUMBERS";
        public static final String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
        public static final String READ_SMS = "android.permission.READ_SMS";
        public static final String RECEIVE_MMS = "android.permission.RECEIVE_MMS";
        public static final String RECEIVE_SMS = "android.permission.RECEIVE_SMS";
        public static final String RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH";
        public static final String RECORD_AUDIO = "android.permission.RECORD_AUDIO";
        public static final String SEND_SMS = "android.permission.SEND_SMS";
        public static final String USE_SIP = "android.permission.USE_SIP";
        public static final String WRITE_CALENDAR = "android.permission.WRITE_CALENDAR";
        public static final String WRITE_CALL_LOG = "android.permission.WRITE_CALL_LOG";
        public static final String WRITE_CONTACTS = "android.permission.WRITE_CONTACTS";
        public static final String WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE";
    }

    /**
     * 权限组
     */
    public static class PermissionGroup {
        public static final String ACTIVITY_RECOGNITION = "android.permission-group.ACTIVITY_RECOGNITION";
        public static final String CALENDAR = "android.permission-group.CALENDAR";
        public static final String CALL_LOG = "android.permission-group.CALL_LOG";
        public static final String CAMERA = "android.permission-group.CAMERA";
        public static final String CONTACTS = "android.permission-group.CONTACTS";
        public static final String LOCATION = "android.permission-group.LOCATION";
        public static final String MICROPHONE = "android.permission-group.MICROPHONE";
        public static final String NEARBY_DEVICES = "android.permission-group.NEARBY_DEVICES";
        public static final String PHONE = "android.permission-group.PHONE";
        public static final String SENSORS = "android.permission-group.SENSORS";
        public static final String SMS = "android.permission-group.SMS";
        public static final String STORAGE = "android.permission-group.STORAGE";
    }
}
